OT: SUM zapornych a kladnych cisel (FireBird)

Otázka od: bleak

29. 6. 2004 16:21

zdravim,
potrebuji udelat jednim SQL dotazem soucet cisel z jednoho sloupce tabulky
do vysledku s dvema sloupci, tak aby v jednom byla secteny kladna a v druhem
zaporna cisla. Zkousel jsem laborovat s LEFT JOIN ale dotaz trval tak
dlouho, ze jsem to stopnul.
Prosim o tipy jak to resit... Jde to vubec?

bleak



Odpovedá: Rostislav Lekes

29. 6. 2004 16:39

CREATE PROCEDURE SOUCTY
RETURNS (
    KLADNA INTEGER,
    ZAPORNA INTEGER
    )
AS
DECLARE VARIABLE POMOCNA INTEGER;
BEGIN
  KLADNA = 0;
  ZAPORNA = 0;
  FOR SELECT CISLO FROM TABULKA INTO :POMOCNA
  DO
       IF (:POMOCNA<0) THEN
       BEGIN
            ZAPORNA = ZAPORNA + :POMOCNA;
       END ELSE BEGIN
             KLADNA = KLADNA + :POMOCNA;
       END

  SUSPEND;
END

Pisu to rovnou sem, tak doufam, ze tam neni chyba   Rosta.

----- Original Message -----
From: "bleak" <bleak@mvesely.com>
To: <delphi-l@clexpert.cz>
Sent: Tuesday, June 29, 2004 5:01 PM
Subject: OT: SUM zapornych a kladnych cisel (FireBird)


> zdravim,
> potrebuji udelat jednim SQL dotazem soucet cisel z jednoho sloupce tabulky
> do vysledku s dvema sloupci, tak aby v jednom byla secteny kladna a v
druhem
> zaporna cisla. Zkousel jsem laborovat s LEFT JOIN ale dotaz trval tak
> dlouho, ze jsem to stopnul.
> Prosim o tipy jak to resit... Jde to vubec?
>
> bleak
>
>
>
>
>
>
>


Odpovedá: Ondrej Kelle

29. 6. 2004 17:00

> CREATE PROCEDURE SOUCTY
> RETURNS (
> KLADNA INTEGER,
> ZAPORNA INTEGER
> )
> AS
> DECLARE VARIABLE POMOCNA INTEGER;
> BEGIN
> KLADNA = 0;
> ZAPORNA = 0;
> FOR SELECT CISLO FROM TABULKA INTO :POMOCNA
> DO
> IF (:POMOCNA<0) THEN
> BEGIN
> ZAPORNA = ZAPORNA + :POMOCNA;
> END ELSE BEGIN
> KLADNA = KLADNA + :POMOCNA;
> END
>
> SUSPEND;
> END
>
> Pisu to rovnou sem, tak doufam, ze tam neni chyba   Rosta.

Myslim, ze v tom selecte si zabudol podmienku WHERE CISLO IS NOT NULL.

HTH
TOndrej


Odpovedá: Rostislav Lekes

29. 6. 2004 18:03


----- Original Message -----
From: "Ondrej Kelle" <o.kelle@digitalpublishing.de>
To: <delphi-l@clexpert.cz>
Sent: Tuesday, June 29, 2004 5:49 PM
Subject: Re: SUM zapornych a kladnych cisel (FireBird)


> > CREATE PROCEDURE SOUCTY
> > RETURNS (
> > KLADNA INTEGER,
> > ZAPORNA INTEGER
> > )
> > AS
> > DECLARE VARIABLE POMOCNA INTEGER;
> > BEGIN
> > KLADNA = 0;
> > ZAPORNA = 0;
> > FOR SELECT CISLO FROM TABULKA INTO :POMOCNA
> > DO
> > IF (:POMOCNA<0) THEN
> > BEGIN
> > ZAPORNA = ZAPORNA + :POMOCNA;
> > END ELSE BEGIN
> > KLADNA = KLADNA + :POMOCNA;
> > END
> >
> > SUSPEND;
> > END
> >
> > Pisu to rovnou sem, tak doufam, ze tam neni chyba   Rosta.
>
> Myslim, ze v tom selecte si zabudol podmienku WHERE CISLO IS NOT NULL.
>
> HTH
> TOndrej

Anebo jsem predpokladal field not null ?  
Jasne, mas pravdu, ale tohle je jenom nakopnuti ...
Rosta

Odpovedá: bleak

29. 6. 2004 18:01

dekuji za odpoved, zapomnel jsem napsat, ze bych to chtel relizovat jen SQL
dotazem, ne ulozenou procedurou.
Ale asi vyuziji vas navrh.

bleak

----- Original Message -----
From: "Ondrej Kelle" <o.kelle@digitalpublishing.de>
To: <delphi-l@clexpert.cz>
Sent: Tuesday, June 29, 2004 5:49 PM
Subject: Re: SUM zapornych a kladnych cisel (FireBird)


> > CREATE PROCEDURE SOUCTY
> > RETURNS (
> > KLADNA INTEGER,
> > ZAPORNA INTEGER
> > )
> > AS
> > DECLARE VARIABLE POMOCNA INTEGER;
> > BEGIN
> > KLADNA = 0;
> > ZAPORNA = 0;
> > FOR SELECT CISLO FROM TABULKA INTO :POMOCNA
> > DO
> > IF (:POMOCNA<0) THEN
> > BEGIN
> > ZAPORNA = ZAPORNA + :POMOCNA;
> > END ELSE BEGIN
> > KLADNA = KLADNA + :POMOCNA;
> > END
> >
> > SUSPEND;
> > END
> >
> > Pisu to rovnou sem, tak doufam, ze tam neni chyba   Rosta.
>
> Myslim, ze v tom selecte si zabudol podmienku WHERE CISLO IS NOT NULL.
>
> HTH
> TOndrej
>
>


Odpovedá: Zdenek Janis

29. 6. 2004 20:59

A neumi FB neco takoveho:

select
 (select sum(cislo) from tbl where cislo < 0) as zaporna,
 (select sum(cislo) from tbl where cislo >= 0) as kladna;

  zaporna | kladna
---------+--------
      -12 | 14
(1 radka)

Odzkouseno na PostgreSQL.

bleak napsal(a):
> jen SQL
> dotazem, ne ulozenou procedurou.

--
S pozdravem
                 Zdenek Janis
-----------------------------
Tento e-mail neobsahuje VIRY,
jelikoz nepochazi z prostredi
systemu M$ Windows!!!

Odpovedá: Milan Tomes

30. 6. 2004 5:59

Zkus tohle - bohuzel to neumi vratit v jednom zaznamu, ale ve dvou:

select sum(cena) as cena from etssprace where cena < 1000
union all
select sum(cena) as cena from etssprace where cena >= 1000

V prvnim zaznamu je suma vsech zaznamu s cenou < 1000 a v druhem zaznamu je
cena >= 1000

HTH

S pozdravem

Milan Tomes


> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of bleak
> Sent: Tuesday, June 29, 2004 6:58 PM
>
> dekuji za odpoved, zapomnel jsem napsat, ze bych to chtel
> relizovat jen SQL
> dotazem, ne ulozenou procedurou.


Odpovedá: Milan Tomes

30. 6. 2004 6:00

Tak jeste jinak - tohle funguje rychle a vraci to v jednom radku:

select (select sum(cena) from etssprace where cena < 1000) as cena_1000,
(select sum(cena) from etssprace where cena >= 1000) as cena_1000000 from
rdb$database

S pozdravem

Milan Tomes


> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Milan Tomes
> Sent: Wednesday, June 30, 2004 6:43 AM
>
> Zkus tohle - bohuzel to neumi vratit v jednom zaznamu, ale ve dvou:
>
> select sum(cena) as cena from etssprace where cena < 1000
> union all
> select sum(cena) as cena from etssprace where cena >= 1000


Odpovedá: petr palicka

30. 6. 2004 7:01

ahoj,

   pokud se jedna o FB 1.5, tak pouzij cond.
v pripade FB 1.0 bys moh zkusit jeste poddotaz.

peca

Odpovedá: bleak

30. 6. 2004 22:00

zkusil jsem tohle:

select ucet,
(select sum(castka) from platby t2 where castka < 0 and t1.ucet=t2.ucet AND
doklad='992') as zaporna,
(select sum(castka) from platby t3 where castka >= 0 and t1.ucet=t3.ucet AND
doklad='992') as kladna from platby t1
group by ucet

SQL dotaz nedobehne ani po 10 minutach. V tabulce je cca 600 000 zaznamu
index pro pole ucet a doklad.
Jak by se dal dotaz vylepsit?

na tento dotaz
select ucet, sum(castka) from platby where castka> 0 and doklad='992'
group by ucet
mam vysledek okamzite


bleak


Odpovedá: Lebeda David

1. 7. 2004 6:19

> select ucet,
> (select sum(castka) from platby t2 where castka < 0 and
> t1.ucet=t2.ucet AND doklad='992') as zaporna, (select sum(castka) from
> platby t3 where castka >= 0 and t1.ucet=t3.ucet AND doklad='992') as
> kladna from platby t1 group by ucet
>
> SQL dotaz nedobehne ani po 10 minutach. V tabulce je cca 600 000
> zaznamu index pro pole ucet a doklad. Jak by se dal dotaz vylepsit?
>
> na tento dotaz
> select ucet, sum(castka) from platby where castka> 0 and doklad='992'
> group by ucet mam vysledek okamzite

Ahoj,

mozna neco napovi plan dotazu, me napada toto:

1) V ramci prehlednosti, jednoznacnosti apod. doplnit ke kazdemu pouzitemu poli
i
jmeno tabulky, ze ktere pochazi (to nesouvisi s rychlosti, ale s citelnosti)

2) Zjistil jsem, ze ma-li dotaz napr. ve where casti podminku na vice sloupcu z
tabulky,
je velmi drasticky rozdil v rychlosti, mas-li indexy na kazdy sloupec
samostatne, nebo i
jeden index pres vsechny takove sloupce. Doporucuji proto zkusit zalozit index
na trojici
sloupcu castka, doklad, ucet.

Dej vedet, jak to dopadlo.

David Lebeda

Odpovedá: Jan Novak

1. 7. 2004 6:42

> (select sum(castka) from platby t2 where castka < 0 and
t1.ucet=t2.ucet AND
> doklad='992') as zaporna,

co tak zkusit ve vyrazu jine poradi: nejdriv doklad, pak ucet a az
nakonec castka? Proste dat jako prvni neco, ceho vysledkem bude (podle
indexu) nejmin zaznamu, ktere by se pak mohli projit i bez indexu.


Odpovedá: Jan Novak

1. 7. 2004 7:19

> select ucet,
> (select sum(castka) from platby t2 where castka < 0
> and t1.ucet=t2.ucet AND doklad='992') as zaporna,
> (select sum(castka) from platby t3 where castka >= 0
> and t1.ucet=t3.ucet AND doklad='992') as kladna
> from platby t1 group by ucet

Az ted jsem si vsimnul, ze tam mas 'group by'. To pak nemuze byt
'zaporna' ale 'sum(zaporna)' nebo jina agregacni funkce, treba max().
Jenze to by ti vyslo pekny hausnumero! a hlavne by se to zbytecne
opakovane pocitalo.

Ja bych nedelal 'group by', ale 'select distinct ucet' a az k nemu pro
kazdy radek pocital sumy.


Odpovedá: Jakub Dusek

1. 7. 2004 8:23

To vyplyva i ze samotne logiky indexu, kdyz udelam 3 indexy na 3 pole
s nizkou selektivitou tak si optimalizator moc nepomuze pokud pouzije
kterykoliv z nich. Slozeny index na tato 3 pole muze mit selektivitu
dobrou.

Dalsi otazka je ale vyuzitelnost takoveho indexu. Treba Oracle umi
vyuzit index pomoci SKIP SCAN i pokud ve WHERE neni prvni pole z
indexu, nevim jak jsou na tom ostatni DB servery.

Navrh toho indexu je teda potreba udelat i s ohledem na ostatni dotazy
a popremyslet i nad poradim poli.

Jakub Dusek
----------------------------------------------------------------------
web: http://www.corexpert.com, mobile: +420 604 615 795, ICQ: 86063232
odesilani smsek, vizitek, log a melodii, snadna integrace do Vaseho IS
     => Sms GateKeeper, Sms GateKeeper Service

======================================================================
Thursday, July 1, 2004, 7:13:01 AM, you wrote:

LD> 2) Zjistil jsem, ze ma-li dotaz napr. ve where casti podminku na vice
sloupcu z tabulky,
LD> je velmi drasticky rozdil v rychlosti, mas-li indexy na kazdy sloupec
samostatne, nebo i
LD> jeden index pres vsechny takove sloupce. Doporucuji proto
LD> zkusit zalozit index na trojici
LD> sloupcu castka, doklad, ucet.


Odpovedá: Lstiburek Pavel

1. 7. 2004 10:01

a co takhle:

SELECT uucty.ucet, zaporna, kladna
    FROM (SELECT DISTINCT ucet FROM platby WHERE doklad = '992' ) as ucty
                     INNER JOIN
               (SELECT ucet SUM(Casta) AS zaporna FROM PLATBY WHERE doklad =
'992' AND castka < 0 GROUP BY ucet ) AS zaporna
                         ON ucty.ucet = zaporna.ucty
                     INNER JOIN
               (SELECT ucet SUM(Casta) AS kladny FROM PLATBY WHERE doklad =
'992' AND castka > 0 GROUP BY ucet ) AS kladna
                         ON ucty.ucet = kladna.ucty

Pavel

> From: Lebeda David [mailto:david.lebeda@comarr.cz]
> > select ucet,
> > (select sum(castka) from platby t2 where castka < 0 and
> > t1.ucet=t2.ucet AND doklad='992') as zaporna, (select
> sum(castka) from
> > platby t3 where castka >= 0 and t1.ucet=t3.ucet AND doklad='992') as
> > kladna from platby t1 group by ucet
> >
> > SQL dotaz nedobehne ani po 10 minutach. V tabulce je cca 600 000
> > zaznamu index pro pole ucet a doklad. Jak by se dal dotaz vylepsit?
> >
> > na tento dotaz
> > select ucet, sum(castka) from platby where castka> 0 and
> doklad='992'
> > group by ucet mam vysledek okamzite
>

Odpovedá: bleak

1. 7. 2004 22:03

dekuji vsem za tipy a rady, vytvoril jsem indexy a dosel jsem k tomuto

select distinct(t1.ucet),
(select sum(t2.castka) from platby t2 where t2.doklad='992' and
t1.ucet=t2.ucet and castka<0 AND priznak=0) as zaporna1,
(select sum(t2.castka) from platby t2 where t2.doklad='992' and
t1.ucet=t2.ucet and castka>0 AND priznak=0) as kladna1,
from platby t1 where t1.doklad='992'
group by ucet

chodi to rychle (3 sec), ale skoncil jsem, kdyz se zacal delat vyber podle
datumu od-do, tam je plan vzdycky natural.
jdu vyrobit stored procedure

bleak